package com.bubblegumproject.ogo.tx;

import com.bubblegumproject.ogo.component.injection.AbstractDependencyInjector;
import com.bubblegumproject.ogo.component.injection.Injector;
import com.bubblegumproject.ogo.action.Context;

import javax.persistence.*;
import java.util.Collection;

/**
 * Inject the current transaction, as represented by the JPA EntityManager, into a component that requires.
 *
 * @author Azubuko Obele (buko.obele@gmail.com)
 */
public class CurrentTransactionDependencyInjector extends AbstractDependencyInjector {

    public void inject(Collection<Injector> injectors, Context context) {
        for (Injector injector : injectors) {
            if (injector.getTargetType().equals(EntityManager.class)) {
                injector.inject(new EntityManagerProxy());
            }
        }
    }

    private static class EntityManagerProxy implements EntityManager {

        public EntityManager current() {
            return Transaction.current();
        }

        public void persist(Object object) {
            current().persist(object);
        }

        public <T> T merge(T t) {
            return current().merge(t);
        }

        public void remove(Object object) {
            current().remove(object);
        }

        public <T> T find(Class<T> aClass, Object object) {
            return current().find(aClass, object);
        }

        public <T> T getReference(Class<T> aClass, Object object) {
            return current().getReference(aClass, object);
        }

        public void flush() {
            current().flush();
        }

        public void setFlushMode(FlushModeType flushModeType) {
            current().setFlushMode(flushModeType);
        }

        public FlushModeType getFlushMode() {
            return current().getFlushMode();
        }

        public void lock(Object object, LockModeType lockModeType) {
            current().lock(object, lockModeType);
        }

        public void refresh(Object object) {
            current().refresh(object);
        }

        public void clear() {
            current().clear();
        }

        public boolean contains(Object object) {
            return current().contains(object);
        }

        public Query createQuery(String string) {
            return current().createQuery(string);
        }

        public Query createNamedQuery(String string) {
            return current().createNamedQuery(string);
        }

        public Query createNativeQuery(String string) {
            return current().createNativeQuery(string);
        }

        public Query createNativeQuery(String string, Class aClass) {
            return current().createNativeQuery(string, aClass);
        }

        public Query createNativeQuery(String string, String string1) {
            return current().createNativeQuery(string, string1);
        }

        public void joinTransaction() {
            current().joinTransaction();
        }

        public Object getDelegate() {
            return current().getDelegate();
        }

        public void close() {
            current().close();
        }

        public boolean isOpen() {
            return current().isOpen();
        }

        public EntityTransaction getTransaction() {
            return current().getTransaction();
        }
    }
}
